// Copyright 2024 Vadim Kharitonovich
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package packet

import (
	"errors"
)

type Version struct {
	Major, Minor, Patch uint8
}

var version = Version{0, 0, 1}

func GetVersion() Version {
	return version
}

var (
	ErrMalformed = errors.New("malformed packet")
)

const (
	VersionMajorSize       = 1
	VersionMinorSize       = 1
	VersionPatchSize       = 1
	VersionSize            = VersionMajorSize + VersionMinorSize + VersionPatchSize
	MessageCodeSize        = 1
	HeaderSize             = VersionSize + MessageCodeSize
	BalancedEntryIndexSize = 8
	RequestHeaderSize      = HeaderSize
	ResponseHeaderSize     = HeaderSize + BalancedEntryIndexSize
)

const (
	RequestSizeMax              = RequestHeaderSize + BalancedEntryIndexSize // currently we have no any payload
	RequestRetentionPayloadSize = BalancedEntryIndexSize
	ResponseSizeMax             = RequestHeaderSize + 512
)

type (
	MessageCode         uint8
	RequestMessageCode  MessageCode
	ResponseMessageCode MessageCode
)

const (
	_ RequestMessageCode = iota
	RequestNext
	RequestRetain
)

func (r RequestMessageCode) Next() bool {
	return r == RequestNext
}

func (r RequestMessageCode) Retain() bool {
	return r == RequestRetain
}

const (
	_ ResponseMessageCode = iota
	ResponseNext
)

const (
	ResponseCodeUnsupported ResponseMessageCode = 254
	ResponseCodeErr         ResponseMessageCode = 255
)

func UnserializeVersion(buf []byte) Version {
	return Version{
		Major: buf[0],
		Minor: buf[1],
		Patch: buf[2],
	}
}

func SerializeVersion(version *Version, buf []byte) {
	buf[0] = version.Major
	buf[1] = version.Minor
	buf[2] = version.Patch
}

func GetMessageCode[C RequestMessageCode | ResponseMessageCode](buf []byte) C {
	return C(buf[3])
}

func SetMessageCode[C RequestMessageCode | ResponseMessageCode](c C, buf []byte) {
	buf[3] = byte(c)
}
